package com.apes.fn.server.productRequire;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.crm.customerExpand.FnCustomerExpandRepository;
import com.apes.scm.masterdata.enumeration.model.BusinessParam;
import com.apes.scm.masterdata.enumeration.repository.BusinessParamRepository;
import com.apes.fn.mdm.purchase.PurchasingGroupRepository;
import com.apes.fn.server.productRequireManage.model.ReplenishmentBusinessImpAbstract;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.party.model.Corporate;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.CorporateRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrderItem;
import com.apes.scm.pur.purchaseOrder.repository.PurchaseOrderRepository;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述 供应商平台订单服务
 *
 * @ClassName SupplierPurchaseOrder
 * @Description 描述
 * @Author lilong
 * @Date 2023/2/13 15:28
 * @Version 1.0
 */
@Service("supplierPurchaseOrderService")
public class SupplierPurchaseOrderService extends ReplenishmentBusinessImpAbstract {

    @Autowired
    private PartyRoleRepository partyRoleRepository;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private TaxService taxService;

    @Autowired
    private ProductRequireRepository productRequireRepository;

    @Autowired
    private PurchaseOrderRepository purchaseOrderRepository;

    @Autowired
    private ProductUomRepository productUomRepository;

    @Autowired
    private PurchasingGroupRepository purchasingGroupRepository;

    @Autowired
    private ProductRequireItemRepository productRequireItemRepository;

    @Autowired
    private RequireLogisticsRepository requireLogisticsRepository;
    @Autowired
    private StoreRepository storeRepository;

    @Autowired
    private FnCustomerExpandRepository fnCustomerExpandRepository;

    @Autowired
    private DeptRepository deptRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private CorporateRepository corporateRepository;

    @Autowired
    private ProductAccountService productAccountService;
    @Autowired
    private EnumerationRepository enumerationRepository;



    /**
     * 服务方案单创建供应商平台订单
     * @param require 要货单
     */
    public void CreatePurchaseOrder(ProductRequire require,SimpleRequest request){
        List<ProductRequireItem> ProductRequireItems = require.getProductRequireItems().stream()
                .filter(requireItem -> ( Objects.nonNull(requireItem.getChannelType()) && (requireItem.getChannelType()==1 ||requireItem.getChannelType()==2))
                ).collect(Collectors.toList());
        if (ObjectUtils.isEmpty(ProductRequireItems) || ProductRequireItems.isEmpty()) return;

        //判断询价是否过期 商品状态是否为可系统报价
        List<ProductRequireItem> requrieItem = this.isEnquirySpProduct(ProductRequireItems,require);

        if (ObjectUtils.isEmpty(requrieItem) || requrieItem.isEmpty()) return;
        if(request.getSession()==null){ throw new RuntimeException("用户信息丢失，请刷新页面！"); }
       JSONObject  data = this.dataReplenish(require,requrieItem,request);
        try {
            JSONObject  result = JSON.parseObject(invoke("sp.OrderForm.establishOrderForm", data));
            // 获取供应商平台订单结果
            if(result.getString("body")==null) throw new RuntimeException("订单已生成请勿重复创建!");
            JSONArray body = result.getJSONArray("body");
            if (Objects.nonNull(body)){
                require.getProductRequireItems().forEach(item -> {
                    for (ProductRequireItem  productRequireItem:requrieItem) {
                        if (item.getChannelType()!=null &&item.getId().equals(productRequireItem.getId()))
                            //供应商平台只有整单取消，分配数=要货数
                            item.setQtyAssigned(item.getQtyRequire());
                        //写入库存帐要货制单数量()
                        productAccountService.setProductRequireBilling(item.getProduct(), item.getProductRequire().getLocation(), item.getUom(), -1.0*item.getQtyAssigned(), item.getInnerBusinessKey(), item.getId(),
                                item.getProductRequire().getId(), "supplier", item.getCompany(), item.getProductRequire().getId());
                        productAccountService.setProductPurchasingWay(item.getProduct(), item.getProductRequire().getLocation(), item.getUom(), item.getQtyAssigned(), item.getCompany());
                    }
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 校验商品是否过期是否可系统报价 则取消创建录入要货补货
     * @param ProductRequireItems
     * @param require
     * @return
     */
    public List<ProductRequireItem> isEnquirySpProduct(List<ProductRequireItem> ProductRequireItems,ProductRequire require){
        List<ProductRequireItem> requrieItem = new ArrayList<>();


        for (ProductRequireItem item:ProductRequireItems) {
            //价格前置商品
            if(item.getChannelType()==1){
                JSONObject spProductJson = JSON.parseObject(invoke("sp.SpProduct.findById", MapUtil.mapper("id",item.getSpId())));
                JSONObject spProduct = spProductJson.getJSONObject("body");
                boolean is =  verifyContract(require,spProduct.getJSONObject("spProduct").getJSONObject("supplier").getString("id"),spProduct.getString("partyName"));
                if(spProduct.getJSONObject("spProduct")!=null && "offer".equals(spProduct.getJSONObject("spProduct").getString("productState")) && is){
                    requrieItem.add(item);
                }else{this.verifyEnquiry(require,item);}
            }
            //新平台询价商品
            if(item.getChannelType()==2){
                JSONObject  enquiryJSON =  JSON.parseObject(invoke("sp.enquiryService.findByID",MapUtil.mapper("id",item.getCommodityInquiryOrderId())));
                JSONObject enquiry = enquiryJSON.getJSONObject("body");
                String offerId = item.getOfferId();
                int index = offerId.indexOf("/");
                String quoteResultId = offerId.substring(0, index);
                JSONObject productJSON = JSON.parseObject(invoke("sp.spProduct.findByQuoteResult",MapUtil.mapper("id",quoteResultId)));
                JSONObject product= productJSON.getJSONObject("body");
                boolean is =  verifyContract(require,product.getJSONObject("supplier").getString("id"),product.getString("partyName"));
                if(enquiry!=null&& new Date().getTime()<enquiry.getDate("quoteExpireDate").getTime() && is){
                    requrieItem.add(item);
                }else{this.verifyEnquiry(require,item);}
            }
        }
        return  requrieItem;
    }

    /**
     *合同校验
     * @param require
     */
    private boolean verifyContract(ProductRequire require,String id,String name) {
        PartyRole supplier = partyRoleRepository.findValidSupplier(id, name);
        List<Contract> contracts;
        if (require.getCompany().getParty().getCorporate().isWantInvoice()) {
            contracts = SpringManager.getBean(ContractRepository.class).findValidPlatformSupplierState(supplier);
        } else {
            contracts = SpringManager.getBean(ContractRepository.class).findValidPlatformState(supplier);
        }
        if (contracts == null || contracts.size() == 0) return false;
        return true;
    }

    /**
     * 询价是否过期 商品状态是否为可系统报价校验
     * @param require
     * @param item
     */
    public void verifyEnquiry(ProductRequire require,ProductRequireItem item){
        for (ProductRequireItem productRequireItem:require.getProductRequireItems()) {
            if(productRequireItem.getId().equals(item.getId())){
                double num = productRequireItem.getQtyAssigned()-productRequireItem.getQtyRequire();
                productRequireItem.setQtyAssigned(num<0?0:num);
                productRequireItemRepository.saveAndFlush(productRequireItem);
                productAccountService.setProductRequireBilling(item.getProduct(), item.getProductRequire().getLocation(), item.getUom(),item.getQtyAssigned(), item.getInnerBusinessKey(), item.getId(),
                        item.getProductRequire().getId(), "supplier", item.getCompany(), item.getProductRequire().getId());
            }

        }
    }

    /**
     * 要货补货生成供应商平台订单
     * @param productRequireItem 要货单明细
     * @return
     */
    public boolean CreateSupplierOrder(List<ProductRequireItem> productRequireItem,SimpleRequest request){
        ProductRequire productRequire =  productRequireRepository.findOne(productRequireItem.get(0).getProductRequire().getId());
        List<ProductRequireItem> productRequireItemList = isEnquirySpProduct(productRequireItem,productRequire);
        if(productRequireItemList.size()==0) return true;
        JSONObject  data = this.dataReplenish(productRequire,productRequireItemList,request);
            JSONObject  result = JSON.parseObject(invoke("sp.OrderForm.establishOrderForm", data));
           if(result.getString("body")==null) return false;
            // 获取供应商平台订单结果
            JSONArray body = result.getJSONArray("body");
            if (Objects.nonNull(body)){
                productRequire.getProductRequireItems().forEach(item -> {
                    productRequireItem.forEach(o->{
                        if (item.getId().equals(o.getId()))
                            //供应商平台只有整单取消，分配数=要货数
                            o.setQtyAssigned(o.getQtyRequire());
                        //写入库存帐要货制单数量()
                        productAccountService.setProductRequireBilling(item.getProduct(), item.getProductRequire().getLocation(), item.getUom(), -1.0*item.getQtyAssigned(), item.getInnerBusinessKey(), item.getId(),
                                item.getProductRequire().getId(), "supplier", item.getCompany(), item.getProductRequire().getId());
                    });
                });
                productRequireRepository.save(productRequire);
                return true;
            }
        return false;
    }

    /**
     * 补全供应商平台信息
     * @param require
     * @param requrieItem
     * @return
     */
    public JSONObject dataReplenish(ProductRequire require, List<ProductRequireItem> requrieItem,SimpleRequest request){
        JSONObject data = new JSONObject();

        data.put("require", MapUtil.mapped(require));
        data.put("productRequireItems", MapUtil.mapped(requrieItem));
        String id = productRequireRepository.findByLocationAndById(require.getId());
        data.put("store",MapUtil.mapped(storeRepository.findOne(id)));//联系人
        Dept dept  = deptRepository.findOne(id);
        data.put("dept",MapUtil.mapped(dept));//门店
        data.put("wantInvoice",MapUtil.mapped(productRequireRepository.findByCompanyByPartyByCorporate(require.getId())));//是否开票
        data.put("customerExpand", MapUtil.mapped(fnCustomerExpandRepository.findOne(require.getCustomerExpand().getId())));//车架号
        User user = userRepository.findOne(Integer.valueOf(request.getSession().getUserId()));
        if(user!=null){
            data.put("name", user.getName());
            data.put("mobileNumber", user.getMobileNumber());
        }
        return data;
    }

    /**
     * 供应商平台确认订单生成采购订单
     * @param request 请求对象
     */
    private boolean newOrder(SimpleRequest request) {
        //供应商平台回调订单
        JSONObject orderForm = request.getJO();
        JSONArray orderFormDetailArray = orderForm.getJSONArray("detailList");
        ProductRequire require = productRequireRepository.findOne(orderForm.getString("relatedNumber"));
        PurchaseOrder purchaseOrder = purchaseOrderRepository.findBysupplierRef(orderForm.getString("id"));
        if (Objects.nonNull(purchaseOrder)) {
            return true;
        }
        if (Objects.isNull(require)) return false;//找不到要货单
        require.setExternalState("shipments");//设置要货单第三方单据状态
        //生成采购订单
        purchaseOrder = this.appendPurchaseOrder(require, orderForm);
        if (Objects.isNull(purchaseOrder)) return false;//合同协议为空
        purchaseOrder.setSupplierType("supplier");
        List<PurchaseOrderItem> purchaseItems = new ArrayList<>();
        //采购订单明细
        PurchaseOrder finalPurchaseOrder = purchaseOrder;
        orderFormDetailArray.stream().forEach(item ->{
            JSONObject jsonObject = (JSONObject)item;
            purchaseItems.add(this.appendPurchaseOrderItem(finalPurchaseOrder,jsonObject,orderForm));
        });

        purchaseOrder.setPurchaseItems(purchaseItems);

        double sumAmtTax = Arith.round(purchaseOrder.getPurchaseItems().stream().mapToDouble(purchaseOrderItem -> purchaseOrderItem.getPriceTax()).sum(), 2);
        double sumAmtUntaxed = Arith.round(purchaseOrder.getPurchaseItems().stream().mapToDouble(purchaseOrderItem -> purchaseOrderItem.getPriceSubtotal()).sum(), 2);
        double sumAmtTotal = Arith.round(purchaseOrder.getPurchaseItems().stream().mapToDouble(purchaseOrderItem -> purchaseOrderItem.getPriceTotal()).sum(), 2);
        purchaseOrder.setAmtTax(sumAmtTax);
        purchaseOrder.setAmtTotal(sumAmtTotal);
        purchaseOrder.setAmtWithoutTax(sumAmtUntaxed);
        PurchaseOrder purchaseOrder1 = purchaseOrderRepository.save(purchaseOrder);

        Object invoke = invoke("purchase.order.approve", JSON.toJSONString(purchaseOrder1));
        if (invoke == null) return false;
        purchaseOrderRepository.save(purchaseOrder1);
        require =  productRequireRepository.saveAndFlush(require);
        this.recordpurchaseOrder(purchaseOrder1,require,orderFormDetailArray);
        return true;
    }
    /**
     * 记录采购订单
     * @param purchaseOrder 采购订单
     * @param productRequire 要货单
     * @return
     */
    private void recordpurchaseOrder(PurchaseOrder purchaseOrder,ProductRequire productRequire,JSONArray array){
        for (ProductRequireItem productRequireItem:productRequire.getProductRequireItems()) {
            for (Object object:array) {
                JSONObject o = (JSONObject)object;
                if(o.getString("productRequireItem").equals(productRequireItem.getId())){
                    RequireLogistics requireLogistics = new RequireLogistics();
                    requireLogistics.setOrigin(productRequire.getId());
                    requireLogistics.setOriginBusinessType(productRequire.getInnerBusinessType());
                    requireLogistics.setProduct(productRequireItem.getProduct());
                    requireLogistics.setMessage("订单已确认，生成采购订单【"+ purchaseOrder.getId() +"】");
                    requireLogisticsRepository.saveAndFlush(requireLogistics);
                }
            }

        }
    }

    /**
     * 生成采购订单
     * @param require 要货单
     * @return
     */
    private PurchaseOrder appendPurchaseOrder(ProductRequire require, JSONObject orderForm) {
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        PartyRole supplier = partyRoleRepository.findValidSupplier(orderForm.getJSONObject("supplier").getString("id"), orderForm.getString("partyName"));
        List<Contract> contracts = null;
        if(orderForm.getBoolean("invoicing")){
            contracts = SpringManager.getBean(ContractRepository.class).findValidPlatformSupplierState(supplier);
        }else{
            contracts = SpringManager.getBean(ContractRepository.class).findValidPlatformState(supplier);
        }
        if (contracts==null || contracts.size()==0) return null ;
        Contract contract = contracts.get(0);
        purchaseOrder.setScene(SpringManager.getBean(SceneRepository.class).findOne("PO001"));
        purchaseOrder.setCreator(require.getApproveId().getId());
        purchaseOrder.setProductRequire(require.getId());
        purchaseOrder.setCreateUid(require.getApproveId());
        purchaseOrder.setState("approve");
        purchaseOrder.setClerk(require.getApproveId());
        purchaseOrder.setContract(contract);
        purchaseOrder.setCooperation(contract.getCooperation());
        purchaseOrder.setLocation(require.getLocation());
        purchaseOrder.setSupplier(supplier);
        if(contract.getMoveType()==null){
            Enumeration enumeration = enumerationRepository.findOne("one");
            purchaseOrder.setMoveType(enumeration);
        }else{
            purchaseOrder.setMoveType(contract.getMoveType());
        }
        purchaseOrder.setApproveUid(require.getApproveId());
        purchaseOrder.setOrigin(require.getSource());
        purchaseOrder.setOriginBusinessType(require.getSourceBusinessType());
        purchaseOrder.setOriginTypeName(require.getSourceBusinessTypeName());
        purchaseOrder.setCarryType(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne(contract.getCarryType().getId()));
        purchaseOrder.setProductRequire(require.getId());
        purchaseOrder.setSource(require.getId());
        purchaseOrder.setSupplierRef(orderForm.getString("id"));
        purchaseOrder.setSourceType(require.getInnerBusinessType());
        purchaseOrder.setSourceTypeName(require.getSourceBusinessTypeName());
        //purchaseOrder.setPurchasingGroup(purchasingGroupRepository.getSupplierIdAndDeptId(orderForm.getJSONObject("supplier").getString("id"),orderForm.getString("clientId"))); //采购组
        purchaseOrder.setCarLicense(require.getCustomerExpand().getCarLicense());
        purchaseOrder.setCustomerExpandId(require.getCustomerExpand().getId());
        if ("1007".equals(contract.getCompany().getId())) {
            purchaseOrder.setDept(getBean(DeptRepository.class).findByDeptTypeIdAndCompanyId("000006", require.getLocation().getCompany().getId()));
            purchaseOrder.setCompany(require.getLocation().getCompany());
        } else {
            purchaseOrder.setDept(contract.getDept()); // 是合同的部门
            purchaseOrder.setCompany(contract.getCompany()); // 是合同的公司
        }

        return purchaseOrder;
    }



    /**
     * 生成采购订单明细
     * @param purchaseOrder 采购订单
     * @return
     */
    private PurchaseOrderItem appendPurchaseOrderItem(PurchaseOrder purchaseOrder,JSONObject jsonObject,JSONObject orderForm) {
        PurchaseOrderItem purchaseItem = new PurchaseOrderItem();
        Product product = productRepository.findOne(jsonObject.getString("thirdPartyCoding"));
        PartyRole supplier = partyRoleRepository.findValidSupplier(orderForm.getJSONObject("supplier").getString("id"), orderForm.getString("partyName"));
        purchaseItem.setProduct(product); //商品
        purchaseItem.setTax(taxService.getPurchaseTax(purchaseOrder.getCompany(),supplier, product));//税率
        purchaseItem.setProductUomQty(jsonObject.getInteger("orderQuantity")); //订货数量
        purchaseItem.setPriceUnit(jsonObject.getDouble("taxUnitPrice"));  // 单价
        purchaseItem.setPurchaseOrder(purchaseOrder); //采购订单号
        purchaseItem.setSourceItemId(jsonObject.getString("productRequireItem"));
        purchaseItem.computeAmt();
        conversionUomQty(product,jsonObject,purchaseItem);
        return purchaseItem;
    }

    // 供应商平台 - 生成采购订单 - 单位换算
    private void conversionUomQty(Product product,JSONObject orderForm, PurchaseOrderItem purchaseItem) {
        double requireQty = orderForm.getInteger("orderQuantity"); // 订单数量
        if (product.getUom().isPurchaseFirst()) {
            purchaseItem.setUom(product.getUom());
        } else {
            ProductUom purchaseUom = productUomRepository.findBypurchaseUom(product.getId());
            purchaseItem.setUom(purchaseUom);
            requireQty = product.getUom().computeQty(requireQty, purchaseUom, true);
        }
        purchaseItem.setEffectiveQty(requireQty);
        purchaseItem.setProductUomQty(requireQty);
        purchaseItem.setDemandQty(requireQty);
    }

    /**
     * 供应商订单取消释放要货单
     * @param request 要货单号
     */
    public void cancelOrder(SimpleRequest request){
        ProductRequire productRequire = productRequireRepository.findOne(request.getJO().getString("relatedNumber"));
        JSONArray array  = request.getJO().getJSONArray("detailList");
        for (ProductRequireItem productRequireItem:productRequire.getProductRequireItems()) {
            for (Object o:array) {
                JSONObject jsonObject = (JSONObject)o;
                if(jsonObject.getString("productRequireItem").equals(productRequireItem.getId())){
                    productRequireItem.setQtyAssigned(productRequireItem.getQtyAssigned()-jsonObject.getInteger("orderQuantity"));
                    //写入库存帐要货制单数量()
                    productAccountService.setProductRequireBilling(productRequireItem.getProduct(), productRequireItem.getProductRequire().getLocation(), productRequireItem.getUom(), jsonObject.getInteger("orderQuantity"), productRequireItem.getInnerBusinessKey(), productRequireItem.getId(),
                            productRequireItem.getProductRequire().getId(), "supplier", productRequireItem.getCompany(), productRequireItem.getProductRequire().getId());
                    productAccountService.setProductPurchasingWay(productRequireItem.getProduct(), productRequireItem.getProductRequire().getLocation(), productRequireItem.getUom(), (-1*jsonObject.getInteger("orderQuantity")), productRequireItem.getCompany());

                }
            }
            productRequireItem.getProductRequire().setLastUpdatedStamp(new Date());
            productRequireItemRepository.saveAndFlush(productRequireItem);
        }
    }

    /**
     * 记录要货单明细要货跟踪
     * @param request
     * @return
     */
    private void recordOrderForm(SimpleRequest request){
        JSONObject result = request.getJO();
        ProductRequire require = productRequireRepository.findOne(result.getString("relatedNumber"));
        for (ProductRequireItem productRequireItem:require.getProductRequireItems()) {
            RequireLogistics requireLogistics = new RequireLogistics();
            requireLogistics.setOrigin(require.getId());
            requireLogistics.setOriginBusinessType(require.getInnerBusinessType());
            requireLogistics.setProduct(productRequireItem.getProduct());
            requireLogistics.setMessage("您的订单已发货，供应商平台订单【"+ result.getString("id") +"】");
            requireLogisticsRepository.saveAndFlush(requireLogistics);
        }

    }


    /**
     * 供应商平台确认收货
     * @param request 收货单
     */
    @Listener(topic = "event:stock.pick.thirdParty")
    private void orderFormReceipt(SimpleRequest request){
        JSONObject jo = request.getJO();
        PurchaseOrder order = SpringManager.getBean(PurchaseOrderRepository.class).findOne(jo.getString("origin"));
        if (order == null || Objects.isNull(order.getSupplierRef()) || !"supplier".equals(order.getSupplierType())) return;
        JSONObject data = new JSONObject();
        data.put("order", MapUtil.mapped(order));
        data.put("name", MapUtil.mapped(jo.getJSONObject("doneUid").getString("name")));
        invoke("sp.OrderForm.orderFormReceipt", data);
    }

    /**
     * 根据要货单获取会员扩展表信息
     * @param request
     * @return
     */
    public FnCustomerExpand findFnCustomerExpand(SimpleRequest request){
        JSONObject jo = request.getJO();
        ProductRequire require = productRequireRepository.findOne(jo.getString("relatedNumber"));
        return require.getCustomerExpand();
    }
}
